home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / envcalc.com / UWCALC.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1991-03-15  |  6.7 KB  |  336 lines

  1. {--------------------------------------------------------------}
  2. { UWCALC.PAS                                                   }
  3. { COPYRIGHT (C) USERWARE 1991 ALL RIGHTS RESERVED.             }
  4. { (portions copyright Borland International 1990.)             }
  5. { USERWARE, 4 FALCON LN E, FAIRPORT NY 14450-3312 USA.         }
  6. { VOICE: 716-425-3463. CIS: 71540,3660.                        }
  7. {==============================================================}
  8.  
  9. unit uwcalc;
  10.  
  11. interface
  12.  
  13. type
  14.  csstring=string[15];
  15. const
  16.  cserrst:csstring='Error';
  17.  
  18. const
  19.  csclear  ='C';
  20.  csdecimal='.';
  21.  csplus   ='+';
  22.  csminus  ='-';
  23.  cstimes  ='*';
  24.  csdivide ='÷';
  25.  csequal  ='=';
  26.  csmod    =#15;
  27.  
  28.  cschgsign='±';
  29.  cspercent='%';
  30.  
  31.  cseq  ='≈';
  32.  cslt  ='<';
  33.  csgt  ='>';
  34.  cslteq='≤';
  35.  csgteq='≥';
  36.  csnteq='≡';
  37.  
  38.  csand='&';
  39.  csor ='|';
  40.  csxor='@';
  41.  
  42.  csnot='!';
  43.  cssqrt='√';
  44.  cssqr='²';
  45.  
  46.  csshl='«';
  47.  csshr='»';
  48.  
  49.  csopen ='(';
  50.  csclose=')';
  51.  
  52. const
  53.  csfalse= 0;
  54.  cstrue =-1; { (not 0)==(-1) }
  55.  
  56. {}
  57.  
  58. function calcstr(var result:real; var exp:string):boolean;
  59.  
  60. type
  61.  opstr=string[2];
  62.  
  63. procedure opsub(var s:string;this,that:opstr);
  64. procedure stdsub(var s:string);
  65.  
  66. procedure democalc;
  67.  
  68. {}
  69.  
  70. implementation
  71.  
  72. function calcstr(var result:real; var exp:string):boolean;
  73. type
  74.  tcalcstate=(csfirst,csvalid,cserror);
  75. var
  76.  status:tcalcstate;
  77.  number:csstring;
  78.  sign:char;
  79.  operator:char;
  80.  operand:real;
  81.  
  82.  procedure clear;
  83.  begin
  84.   status:=csfirst;
  85.   sign:=' ';
  86.   operator:=csequal
  87.  end;
  88.  
  89.  procedure calckey(key:char);
  90.  var
  91.   r:real;
  92.  
  93.   procedure error;
  94.   begin
  95.    status:=cserror;
  96.    number:=cserrst;
  97.    sign:=' '
  98.   end;
  99.  
  100.   procedure setnumber(r:real);
  101.   var
  102.    s:string[63];
  103.   begin
  104.    str(r:0:10,s);
  105.    if (s[1]<>csminus)
  106.     then sign:=' '
  107.     else begin
  108.      delete(s,1,1);
  109.      sign:=csminus
  110.     end;
  111.    if length(s)>1+15+10
  112.     then error
  113.     else begin
  114.      while (s[length(s)]='0') do dec(s[0]);
  115.      if (s[length(s)]='.') then dec(s[0]);
  116.      number:=s
  117.     end;
  118.   end;
  119.  
  120.   procedure putnumber(var r:real);
  121.   var
  122.    e:integer;
  123.   begin
  124.    val(sign+number,r,e)
  125.   end;
  126.  
  127.   procedure checkfirst;
  128.   begin
  129.    if (status<>csfirst) then exit;
  130.    status:=csvalid;
  131.    number:='0';
  132.    sign:=' '
  133.   end;
  134.  
  135.   procedure checkunary;
  136.   var
  137.    k:char;
  138.   begin
  139.    if (status<>csfirst) then exit;
  140.  
  141.    checkfirst; k:=key; key:=' ';
  142.    case k of 
  143.     csminus: 
  144.      begin
  145.       sign:=csminus;
  146.       putnumber(operand);
  147.      end;
  148.     csnot:
  149.      begin
  150.       operator:=k;
  151.       status:=csfirst
  152.      end
  153.     else key:=k end
  154.   end;
  155.  
  156.  begin {calckey}
  157.   key:=upcase(key);
  158.   if (status=cserror) and (key<>csclear) then key:=' ';
  159.  
  160.   checkunary;
  161.  
  162.   case key of
  163.  
  164.    #8,#27: {editing keys}
  165.     begin
  166.      checkfirst;
  167.      if (length(number)=1) then number:='0' else dec(number[0])
  168.     end;
  169.  
  170.    '0'..'9':
  171.     begin
  172.      checkfirst;
  173.      if (number='0') then number:='';
  174.      number:=number+key
  175.     end;
  176.  
  177.    csdecimal:
  178.     begin
  179.      checkfirst;
  180.      if (pos(csdecimal,number)=0) then number:=number+csdecimal
  181.     end;
  182.  
  183.    cschgsign:
  184.     if sign=' ' then sign:=csminus else sign:=' ';
  185. (*
  186.    cssqrt:
  187.     begin
  188.      putnumber(r); setnumber(sqrt(r)); putnumber(operand)
  189.     end;
  190.    cssqr:
  191.     begin
  192.      putnumber(r); setnumber(sqr(r)); putnumber(operand)
  193.     end;
  194. *)
  195.    csplus,csminus,cstimes,csdivide,csequal,cschgsign,cspercent,#13,
  196.    csnot,cssqrt,cssqr,
  197.    csand,csor,csxor,csmod,csshl,csshr,
  198.    cslt,csgt,cseq,cslteq,csgteq,csnteq:
  199.     begin
  200.      if (status=csvalid) then begin
  201.       status:=csfirst;
  202.       putnumber(r);
  203.       if (key=cspercent) then case OPERATOR of
  204.        csplus,csminus  : r:=operand * r / 100;
  205.        cstimes,csdivide: r:=r / 100
  206.       end;
  207.       case OPERATOR of
  208.        csplus  : setnumber(operand+r);
  209.        csminus : setnumber(operand-r);
  210.        cstimes : setnumber(operand*r);
  211.        csdivide: if (r=0) then error else setnumber(operand / r);
  212.        csmod   : if (r=0) then error else setnumber(trunc(operand) mod trunc(r));
  213.  
  214.        csnot: setnumber(not trunc(r));
  215.        csxor: setnumber(trunc(operand) xor trunc(r));
  216.        csand: setnumber(trunc(operand) and trunc(r));
  217.        csor : setnumber(trunc(operand) or  trunc(r));
  218. (*
  219.        csshl: setnumber(trunc(operand) shl trunc(r));
  220.        csshr: setnumber(trunc(operand) shr trunc(r));
  221. *)
  222.        cslt: if (operand<r) then setnumber(cstrue) else setnumber(csfalse);
  223.        csgt: if (operand>r) then setnumber(cstrue) else setnumber(csfalse);
  224.        cseq: if (operand=r) then setnumber(cstrue) else setnumber(csfalse);
  225.        csnteq: if (operand<>r) then setnumber(cstrue) else setnumber(csfalse);
  226.        cslteq: if (operand<=r) then setnumber(cstrue) else setnumber(csfalse);
  227.        csgteq: if (operand>=r) then setnumber(cstrue) else setnumber(csfalse);
  228.       end
  229.      end;
  230.      OPERATOR:=key;
  231.      putnumber(operand)
  232.     end; { case key of [operators] }
  233.  
  234.    csclear: clear
  235.   end { case key .. }
  236.  end; {calckey}
  237.  
  238. var
  239.  v,x:byte;
  240. label
  241.  quit;
  242. begin {calcstr}
  243.  
  244.  number:=''; operand:=0; clear;
  245.  x:=length(exp);
  246.  v:=0;
  247.  while (v<>x) and (status<>cserror) do begin
  248.   inc(v);
  249.   if (exp[v]=csclose)
  250.    then begin
  251.     calckey(csequal);
  252.     goto quit
  253.    end
  254.    else if (exp[v]=csopen)
  255.     then begin
  256.      delete(exp,1,v);
  257.      if (not calcstr(result,exp))
  258.       then status:=cserror;
  259.      x:=length(exp);
  260.      v:=0
  261.     end
  262.    else calckey(exp[v])
  263.  end;
  264.  quit:
  265.  if (status=cserror)
  266.   then delete(exp,1,v-1)
  267.   else begin
  268.    exp:=sign+number+copy(exp,v+1,255);
  269.    if (sign=' ') then delete(exp,1,1)
  270.   end;
  271.  result:=operand;
  272.  calcstr:=(status<>cserror)
  273. end;
  274.  
  275. {}
  276.  
  277. procedure opsub(var s:string;this,that:opstr);
  278. var
  279.  v:byte;
  280. label
  281.  scan;
  282. begin
  283.  scan:
  284.   v:=pos(this,s);
  285.    if (v=0) then EXIT;
  286.   delete(s,v,length(this));
  287.   insert(that,s,v);
  288.  goto scan
  289. end;
  290.  
  291. procedure stdsub(var s:string);
  292. begin
  293.  opsub(s,'<=',cslteq); opsub(s,'=<',cslteq);
  294.  opsub(s,'>=',csgteq); opsub(s,'=>',csgteq);
  295.  opsub(s,'==',cseq  );
  296.  opsub(s,'!=',csnteq); opsub(s,'=!',csnteq);
  297.  opsub(s,'<>',csnteq);
  298.  
  299.  opsub(s,'>>',csshr );
  300.  opsub(s,'<<',csshl );
  301.  opsub(s,'\/',cssqrt);
  302.  opsub(s,'^' ,cssqr);
  303.  
  304.  opsub(s,'/' ,csdivide);
  305.  opsub(s,'\' ,csmod );
  306.  opsub(s,'[' ,csopen);
  307.  opsub(s,']' ,csclose);
  308. end;
  309.  
  310. {}
  311.  
  312. procedure democalc;
  313. var
  314.  r:real;
  315.  x,s:string;
  316. begin
  317.  writeln('Available operators include + - / * & | ! < > >= <= == != ( )');
  318.  writeln('Booleans evaluate to 0 (false) or -1 (true)');
  319.  repeat
  320.   write('>'); readln(s); stdsub(s);
  321.  
  322.   x:=s+csequal; {writeln(':',s);}
  323.  
  324.   if calcstr(r,x)
  325.    then writeln('=',r,' ',x)
  326.    else writeln(#19,
  327.     copy(s,1,length(s)-length(x)+1),
  328.      #127,
  329.      copy(x,1,pred(length(x)))
  330.     )
  331.  until (s='')
  332. end;
  333.  
  334. end.
  335.  
  336.